Usage of constant values in JSP code
As JSP developer I always have been disturbed by the lack of support for static constant values. With scriptlets or runtime expressions in <%= %> tags it's none of a problem - but who still uses this kind of coding style? In times of custom tags and the expression language provided by JSP/JSF you more and more refer to objects located in some scope of your application.
Unfortunately the new expression language of JSP still does not support the use of static constant values - you still are forced to use hard-coded string literals throughout your JSPs.
At the end of last year I was working on my first real JSF project and finally found a nifty solution for this kind of problem.
I put all my application wide constants in a single "Constants" class. Then I used a ServletContextListener to put all it's public static fields via introspection in a Map in the application scope (not as JSF backing bean, but as ServletContext attribute) using the key "Constants".
So, as already wrote, I put the Map into an application scoped attribute using a ServletContextListener:
This way I could access all my constants in the JSPs via JSP expression language:
Since the expression language allows you to reference mapped values via Map['key'] or Map.key, I could use the "dot" syntax to mimic a normal static access to the Constants classes fields.
In JSFs expression language you additionally have to use the prefix "applicationScope.", since the normal VariableResolver implementations search for a managed bean by default - which my Map clearly isn't...
I hope this helps you achieve your goal of reusable constant values throughout your application.
Unfortunately the new expression language of JSP still does not support the use of static constant values - you still are forced to use hard-coded string literals throughout your JSPs.
At the end of last year I was working on my first real JSF project and finally found a nifty solution for this kind of problem.
I put all my application wide constants in a single "Constants" class. Then I used a ServletContextListener to put all it's public static fields via introspection in a Map in the application scope (not as JSF backing bean, but as ServletContext attribute) using the key "Constants".
public final class Constants {
/** ID for reference from the ServletContext. */
public static final String ID = "Constants";
// other constants follow, e. g. for the example below:
public static final String TAB_DETAILS = "tabDetails";
...
/** "Cache" holding all public static fields by it's field name */
private static Map nameToValueMap = createNameToValueMap();
/**
* Puts all public static fields via introspection into the resulting Map.
* Uses the name of the field as key to reference it's in the Map.
*
* @return a Map of field names to field values of
* all public static fields of this class
*/
private static Map createNameToValueMap() {
Map result = new HashMap();
Field[] publicFields = Constants.class.getFields();
for (int i = 0; i < publicFields.length; i++) {
Field field = publicFields[i];
String name = field.getName();
try {
result.put(name, field.get(null));
} catch (Exception e) {
System.err.println("Initialization of Constants class failed!");
e.printStackTrace(System.err);
}
}
return result;
}
/**
* Gets the Map of all public static fields.
* The field name is used as key for the value of the field itself.
*
* @return the Map of all public static fields
*/
public static Map getNameToValueMap() {
return nameToValueMap;
}
}So, as already wrote, I put the Map into an application scoped attribute using a ServletContextListener:
...
public void contextInitialized(ServletContextEvent event) {
ServletContext sc = event.getServletContext();
sc.setAttribute(Constants.ID, Constants.getNameToValueMap());
}
...
This way I could access all my constants in the JSPs via JSP expression language:
...
<c:if test="${globalView.linieTab eq Constants.TAB_DETAILS}">
...
Since the expression language allows you to reference mapped values via Map['key'] or Map.key, I could use the "dot" syntax to mimic a normal static access to the Constants classes fields.
In JSFs expression language you additionally have to use the prefix "applicationScope.", since the normal VariableResolver implementations search for a managed bean by default - which my Map clearly isn't...
<h:inputHidden value="#{applicationScope.Constants.TAB_DETAILS}">I hope this helps you achieve your goal of reusable constant values throughout your application.
Labels: HowTo
6 Comments:
At 10:25 PM,
Rob Freundlich said…
You have just saved me *tons* of research. THANK YOU for this technique!!!!!!!!
At 10:50 AM,
Anonym said…
Thank you rob, very usefull, thanks again
At 7:53 PM,
terrafant said…
I have been using the same technique, but it have some drawbacks:
1. If my Constants class have Inner class I still can put all it's content to the map (the key should be the name of the class + "."). But in JSP you will be forced to call something like this:
${Constants["Upload.LOCAL_UPLOAD_DIRECTORY"]}
2. I'm using Netbeans IDE and for scriptlets there is code completion, but for this solution it does not work.
Do you have solutions for these drawbacks?
At 8:08 AM,
René said…
1.) I do not use inner classes in my Constants classes.
What is the advantage in using it?
2.) In scriptlets you can use the constants of your Constants class directly without the ${}-syntax - just add an import or use the fully qualified classname.
At 1:15 AM,
terrafant said…
René, thank you for answer.
1) I have legacy code. Here we have the Constants class that have inner constants classes. I do not want to refactor this class (also it's pretty convenient since all constants are separated by their meaning (like Upload, ImageWorker etc) under one hood - Constants class). I just want to get rid off scriptlets.
2) Yes, as I said we've been using scriptlets and code completion worked with them, but with EL (ie ${}) it does not work. Is there a way to make code completion work for EL?
At 8:27 AM,
René said…
1.) Ok - legacy code is a good point. Have you tried to create a Map of Maps? I do not know if this dot syntax works over several levels, but it's worth a try.
2.) Frankly said: currently I do not work with JSPs any more - so I don't know anything about IDE support. Sorry!
Kommentar veröffentlichen
<< Home